package com.example.launibleplugin.utils

import android.util.Log
import com.example.launibleplugin.constants.BluetoothConstants
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.ConcurrentLinkedQueue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch

/**
 * 日志级别枚举
 * Function: 定义日志的不同级别
 * Note: 用于控制日志输出和过滤
 */
enum class LogLevel(val priority: Int, val tag: String) {
    VERBOSE(2, "V"),
    DEBUG(3, "D"),
    INFO(4, "I"),
    WARN(5, "W"),
    ERROR(6, "E")
}

/**
 * 日志记录项
 * Function: 表示单条日志记录
 * Note: 用于日志缓存和文件写入
 */
data class LogEntry(
    val timestamp: Long,
    val level: LogLevel,
    val tag: String,
    val message: String,
    val throwable: Throwable? = null
) {
    /**
     * Function: 格式化日志条目
     * Return: String - 格式化后的日志字符串
     * Note: 将日志条目格式化为可读字符串
     */
    fun format(): String {
        val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
        val timeStr = dateFormat.format(Date(timestamp))
        val throwableStr = throwable?.let { "\n${Log.getStackTraceString(it)}" } ?: ""
        return "$timeStr ${level.tag}/$tag: $message$throwableStr"
    }
}

/**
 * 日志记录器
 * Function: 提供统一的日志记录功能
 * Note: 支持控制台输出和文件记录，线程安全
 */
object Logger {
    
    private const val MAX_LOG_FILES = 5
    private const val MAX_LOG_FILE_SIZE = 5 * 1024 * 1024 // 5MB
    private const val LOG_FILE_PREFIX = "launible_plugin"
    
    // 配置
    private var isEnabled = true
    private var minLogLevel = LogLevel.DEBUG
    private var enableFileLogging = false
    private var logDirectory: File? = null
    
    // 日志缓存
    private val logQueue = ConcurrentLinkedQueue<LogEntry>()
    private val coroutineScope = CoroutineScope(Dispatchers.IO + Job())
    
    /**
     * Function: 初始化日志记录器
     * Parameter: logDir - 日志文件目录
     * Parameter: enableFile - 是否启用文件日志
     * Parameter: minLevel - 最小日志级别
     * Note: 配置日志记录器的基本参数
     */
    fun initialize(logDir: File? = null, enableFile: Boolean = false, minLevel: LogLevel = LogLevel.DEBUG) {
        this.logDirectory = logDir
        this.enableFileLogging = enableFile && logDir != null
        this.minLogLevel = minLevel
        
        if (enableFileLogging) {
            // 确保日志目录存在
            logDir?.let { dir ->
                if (!dir.exists()) {
                    dir.mkdirs()
                }
                
                // 清理旧日志文件
                cleanupOldLogFiles(dir)
            }
        }
        
        Log.i(BluetoothConstants.LOG_TAG_PLUGIN, "日志记录器初始化完成，文件日志: $enableFileLogging")
    }
    
    /**
     * Function: 设置日志启用状态
     * Parameter: enabled - 是否启用日志
     * Note: 控制日志的全局开关
     */
    fun setEnabled(enabled: Boolean) {
        this.isEnabled = enabled
    }
    
    /**
     * Function: 设置最小日志级别
     * Parameter: level - 最小日志级别
     * Note: 只有达到此级别的日志才会被记录
     */
    fun setMinLogLevel(level: LogLevel) {
        this.minLogLevel = level
    }
    
    /**
     * Function: 记录详细日志
     * Parameter: tag - 日志标签
     * Parameter: message - 日志消息
     * Parameter: throwable - 异常对象（可选）
     * Note: 记录VERBOSE级别的日志
     */
    fun v(tag: String, message: String, throwable: Throwable? = null) {
        log(LogLevel.VERBOSE, tag, message, throwable)
    }
    
    /**
     * Function: 记录调试日志
     * Parameter: tag - 日志标签
     * Parameter: message - 日志消息
     * Parameter: throwable - 异常对象（可选）
     * Note: 记录DEBUG级别的日志
     */
    fun d(tag: String, message: String, throwable: Throwable? = null) {
        log(LogLevel.DEBUG, tag, message, throwable)
    }
    
    /**
     * Function: 记录信息日志
     * Parameter: tag - 日志标签
     * Parameter: message - 日志消息
     * Parameter: throwable - 异常对象（可选）
     * Note: 记录INFO级别的日志
     */
    fun i(tag: String, message: String, throwable: Throwable? = null) {
        log(LogLevel.INFO, tag, message, throwable)
    }
    
    /**
     * Function: 记录警告日志
     * Parameter: tag - 日志标签
     * Parameter: message - 日志消息
     * Parameter: throwable - 异常对象（可选）
     * Note: 记录WARN级别的日志
     */
    fun w(tag: String, message: String, throwable: Throwable? = null) {
        log(LogLevel.WARN, tag, message, throwable)
    }
    
    /**
     * Function: 记录错误日志
     * Parameter: tag - 日志标签
     * Parameter: message - 日志消息
     * Parameter: throwable - 异常对象（可选）
     * Note: 记录ERROR级别的日志
     */
    fun e(tag: String, message: String, throwable: Throwable? = null) {
        log(LogLevel.ERROR, tag, message, throwable)
    }
    
    /**
     * Function: 核心日志记录方法
     * Parameter: level - 日志级别
     * Parameter: tag - 日志标签
     * Parameter: message - 日志消息
     * Parameter: throwable - 异常对象（可选）
     * Note: 统一的日志记录入口
     */
    private fun log(level: LogLevel, tag: String, message: String, throwable: Throwable? = null) {
        if (!isEnabled || level.priority < minLogLevel.priority) {
            return
        }
        
        try {
            // 控制台输出
            when (level) {
                LogLevel.VERBOSE -> Log.v(tag, message, throwable)
                LogLevel.DEBUG -> Log.d(tag, message, throwable)
                LogLevel.INFO -> Log.i(tag, message, throwable)
                LogLevel.WARN -> Log.w(tag, message, throwable)
                LogLevel.ERROR -> Log.e(tag, message, throwable)
            }
            
            // 文件记录
            if (enableFileLogging) {
                val logEntry = LogEntry(
                    timestamp = System.currentTimeMillis(),
                    level = level,
                    tag = tag,
                    message = message,
                    throwable = throwable
                )
                
                logQueue.offer(logEntry)
                
                // 异步写入文件
                coroutineScope.launch {
                    writeLogsToFile()
                }
            }
            
        } catch (e: Exception) {
            // 避免日志记录本身出错导致的循环
            Log.e(BluetoothConstants.LOG_TAG_PLUGIN, "日志记录失败", e)
        }
    }
    
    /**
     * Function: 将日志写入文件
     * Note: 异步将缓存的日志写入文件
     */
    private suspend fun writeLogsToFile() {
        val logDir = logDirectory ?: return
        
        try {
            val currentLogFile = getCurrentLogFile(logDir)
            if (currentLogFile == null) {
                Log.w(BluetoothConstants.LOG_TAG_PLUGIN, "无法创建日志文件")
                return
            }
            
            // 检查文件大小，如果超过限制则创建新文件
            if (currentLogFile.length() > MAX_LOG_FILE_SIZE) {
                rotateLogFiles(logDir)
            }
            
            // 批量写入日志
            val logsToWrite = mutableListOf<LogEntry>()
            while (logQueue.isNotEmpty() && logsToWrite.size < 100) {
                logQueue.poll()?.let { logsToWrite.add(it) }
            }
            
            if (logsToWrite.isNotEmpty()) {
                FileWriter(currentLogFile, true).use { writer ->
                    logsToWrite.forEach { entry ->
                        writer.write(entry.format() + "\n")
                    }
                    writer.flush()
                }
            }
            
        } catch (e: IOException) {
            Log.e(BluetoothConstants.LOG_TAG_PLUGIN, "写入日志文件失败", e)
        }
    }
    
    /**
     * Function: 获取当前日志文件
     * Parameter: logDir - 日志目录
     * Return: File? - 当前日志文件
     * Note: 获取或创建当前使用的日志文件
     */
    private fun getCurrentLogFile(logDir: File): File? {
        return try {
            val dateFormat = SimpleDateFormat("yyyyMMdd", Locale.getDefault())
            val dateStr = dateFormat.format(Date())
            val fileName = "${LOG_FILE_PREFIX}_$dateStr.log"
            
            File(logDir, fileName).apply {
                if (!exists()) {
                    createNewFile()
                }
            }
        } catch (e: Exception) {
            Log.e(BluetoothConstants.LOG_TAG_PLUGIN, "创建日志文件失败", e)
            null
        }
    }
    
    /**
     * Function: 轮转日志文件
     * Parameter: logDir - 日志目录
     * Note: 当日志文件过大时创建新文件
     */
    private fun rotateLogFiles(logDir: File) {
        try {
            val timeFormat = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
            val timeStr = timeFormat.format(Date())
            val fileName = "${LOG_FILE_PREFIX}_$timeStr.log"
            
            File(logDir, fileName).createNewFile()
            
            // 清理旧文件
            cleanupOldLogFiles(logDir)
            
        } catch (e: Exception) {
            Log.e(BluetoothConstants.LOG_TAG_PLUGIN, "轮转日志文件失败", e)
        }
    }
    
    /**
     * Function: 清理旧日志文件
     * Parameter: logDir - 日志目录
     * Note: 删除超过数量限制的旧日志文件
     */
    private fun cleanupOldLogFiles(logDir: File) {
        try {
            val logFiles = logDir.listFiles { _, name ->
                name.startsWith(LOG_FILE_PREFIX) && name.endsWith(".log")
            }?.sortedByDescending { it.lastModified() }
            
            if (logFiles != null && logFiles.size > MAX_LOG_FILES) {
                logFiles.drop(MAX_LOG_FILES).forEach { file ->
                    if (file.delete()) {
                        Log.d(BluetoothConstants.LOG_TAG_PLUGIN, "删除旧日志文件: ${file.name}")
                    }
                }
            }
        } catch (e: Exception) {
            Log.e(BluetoothConstants.LOG_TAG_PLUGIN, "清理日志文件失败", e)
        }
    }
    
    /**
     * Function: 获取日志统计信息
     * Return: Map<String, Any> - 日志统计数据
     * Note: 返回日志记录的统计信息
     */
    fun getLogStats(): Map<String, Any> {
        val logDir = logDirectory
        val stats = mutableMapOf<String, Any>(
            "enabled" to isEnabled,
            "minLevel" to minLogLevel.name,
            "fileLogging" to enableFileLogging,
            "queueSize" to logQueue.size
        )
        
        if (logDir != null && logDir.exists()) {
            val logFiles = logDir.listFiles { _, name ->
                name.startsWith(LOG_FILE_PREFIX) && name.endsWith(".log")
            }
            
            if (logFiles != null) {
                stats["logFileCount"] = logFiles.size
                stats["totalLogSize"] = logFiles.sumOf { it.length() }
            }
        }
        
        return stats
    }
    
    /**
     * Function: 刷新日志缓存
     * Note: 强制将缓存中的日志写入文件
     */
    fun flush() {
        if (enableFileLogging) {
            coroutineScope.launch {
                writeLogsToFile()
            }
        }
    }
}